#include "ChartWidget.h"
#include <QDateTime>
#include <QLinearGradient>
#include <QPen>
#include <QApplication>
#include <QPalette>
#include <QDebug>
#include <QLabel>
#include <QSqlError>
#include <qmutex.h>

// 定义常量，便于调整和维护
const int MAX_POINTS_PER_BUFFER = 10000;  // 每个缓冲区最多保留的点数
const double DEFAULT_TIME_WINDOW = 5.0; // 默认时间窗口(秒)，修改为5秒
const double Y_AXIS_PADDING_PERCENT = 0.05; // Y轴上下留白比例，修改为5%确保数据占据90%位置
const int BATCH_SIZE = 1000;              // 批处理大小，每次处理的最大点数

ChartWidget::ChartWidget(QWidget *parent)
    : QWidget(parent),
    m_mainLayout(new QVBoxLayout(this)),
    m_startTime(QDateTime::currentMSecsSinceEpoch()),
    m_updateTimer(new QTimer(this)),
    m_timeWindow(DEFAULT_TIME_WINDOW),
    m_yAxisUpdateCounter(0),
    m_yAxisUpdateInterval(10), // 从1增加到10，减少Y轴更新频率
    m_ecgDataBatchCounter(0),
    m_updatingEnabled(true),  // 默认启用更新
    m_bufferCleanTimer(new QTimer(this)) // 新增缓冲区清理定时器
{
    // 初始化缓冲区
    for (int i = 0; i < 3; i++) {
        m_eegBuffer[i].reserve(MAX_BUFFER_SIZE);
    }

    for (int i = 0; i < 8; i++) {
        m_ecgBuffer[i].reserve(MAX_BUFFER_SIZE);
    }

    for (int i = 0; i < 2; i++) {
        m_gsrBuffer[i].reserve(MAX_BUFFER_SIZE);
    }

    // 初始化Y轴范围记忆
    m_eegYRange = QPair<double, double>(-150, 150);
    m_ecgYRange = QPair<double, double>(-100, 300);
    m_gsrYRange = QPair<double, double>(-1000, 1000);

    // 创建EEG图表（3通道）
    QStringList eegChannels = {"FP1", "FPZ", "FP2"};
    m_eegChartView = createChartView("EEG 脑电实时监测", "幅值 (μV)", eegChannels, 3);
    m_eegAxisX = qobject_cast<QValueAxis*>(m_eegChartView->chart()->axes(Qt::Horizontal).first());
    m_eegAxisY = qobject_cast<QValueAxis*>(m_eegChartView->chart()->axes(Qt::Vertical).first());

    // 创建ECG图表（8通道）
    QStringList ecgChannels;
    for (int i = 1; i <= 8; i++) {
        ecgChannels << QString("ECG%1").arg(i);
    }
    m_ecgChartView = createChartView("ECG 心电实时监测", "幅值 (μV)", ecgChannels, 8);
    m_ecgAxisX = qobject_cast<QValueAxis*>(m_ecgChartView->chart()->axes(Qt::Horizontal).first());
    m_ecgAxisY = qobject_cast<QValueAxis*>(m_ecgChartView->chart()->axes(Qt::Vertical).first());

    // 创建GSR图表（2通道）
    QStringList gsrChannels = {"BioZ I", "BioZ Q"};
    m_gsrChartView = createChartView("GSR 皮电实时监测", "阻抗值", gsrChannels, 2);
    m_gsrAxisX = qobject_cast<QValueAxis*>(m_gsrChartView->chart()->axes(Qt::Horizontal).first());
    m_gsrAxisY = qobject_cast<QValueAxis*>(m_gsrChartView->chart()->axes(Qt::Vertical).first());

    // 设置布局
    m_mainLayout->addWidget(m_eegChartView, 1);
    m_mainLayout->addWidget(m_ecgChartView, 1);
    m_mainLayout->addWidget(m_gsrChartView, 1);
    setLayout(m_mainLayout);

    // 设置定时器，用于批量更新图表
    connect(m_updateTimer, &QTimer::timeout, this, &ChartWidget::updateAllCharts);
    m_updateTimer->start(UPDATE_INTERVAL_MS);

    // 设置缓冲区清理定时器，每10秒清理一次缓冲区
    connect(m_bufferCleanTimer, &QTimer::timeout, this, &ChartWidget::cleanOldData);
    m_bufferCleanTimer->start(10000); // 10秒

    // 视觉增强
    QTimer::singleShot(1000, this, &ChartWidget::enhanceVisualization);

    // 设置高优先级，减少卡顿
    m_updateTimer->setTimerType(Qt::PreciseTimer);
}


void ChartWidget::cleanOldData() {
    if (!m_updatingEnabled) return;

    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    double currentT = (currentTime - m_startTime) / 1000.0;
    double cutoffTime = currentT - 5.0; // 保留最近5秒数据

    // 使用互斥锁保护缓冲区操作
    QMutexLocker locker(&m_bufferMutex);

    // 清理EEG缓冲区
    for (int i = 0; i < 3; i++) {
        while (!m_eegBuffer[i].isEmpty() && m_eegBuffer[i].first().x() < cutoffTime) {
            m_eegBuffer[i].removeFirst();
        }
    }

    // 清理ECG缓冲区
    for (int i = 0; i < 8; i++) {
        while (!m_ecgBuffer[i].isEmpty() && m_ecgBuffer[i].first().x() < cutoffTime) {
            m_ecgBuffer[i].removeFirst();
        }
    }

    // 清理GSR缓冲区
    for (int i = 0; i < 2; i++) {
        while (!m_gsrBuffer[i].isEmpty() && m_gsrBuffer[i].first().x() < cutoffTime) {
            m_gsrBuffer[i].removeFirst();
        }
    }

    // 解锁后更新图表，避免长时间持有锁
    locker.unlock();

    // 更新图表，确保显示最新的5秒数据
    updateAllCharts();
}

ChartWidget::~ChartWidget() {
    // Qt 会自动清理 QObjects
    m_updateTimer->stop();
}

// 控制图表更新
void ChartWidget::startUpdating() {
    m_updatingEnabled = true;
    m_updateTimer->start(UPDATE_INTERVAL_MS);
}

void ChartWidget::stopUpdating() {
    m_updatingEnabled = false;
    m_updateTimer->stop();  // 立即停止定时器
}

void ChartWidget::setUpdatingEnabled(bool enabled) {
    m_updatingEnabled = enabled;
    if (enabled) {
        m_updateTimer->start(UPDATE_INTERVAL_MS);
    } else {
        m_updateTimer->stop();
    }
}

QChartView* ChartWidget::createChartView(const QString& title,
                                         const QString& yAxisTitle,
                                         const QStringList& channelNames,
                                         int channelCount) {
    QChart* chart = new QChart();
    QValueAxis* axisX = new QValueAxis();
    QValueAxis* axisY = new QValueAxis();

    // 配置坐标轴
    axisX->setTitleText("时间 (秒)");
    axisX->setTitleFont(QFont("Arial", 10, QFont::Bold));
    axisX->setLabelFormat("%.1f");
    axisX->setTickCount(6);
    axisX->setMinorTickCount(1);
    axisX->setGridLineVisible(true);
    axisX->setMinorGridLineVisible(false);

    axisY->setTitleText(yAxisTitle);
    axisY->setTitleFont(QFont("Arial", 10, QFont::Bold));
    axisY->setLabelFormat("%.1f");
    axisY->setTickCount(5);
    axisY->setMinorTickCount(1);
    axisY->setGridLineVisible(true);
    axisY->setMinorGridLineVisible(false);

    // 美化网格线
    QPen gridPen(QColor(200, 200, 200, 100));
    gridPen.setWidth(1);
    gridPen.setStyle(Qt::DashLine);
    axisX->setGridLinePen(gridPen);
    axisY->setGridLinePen(gridPen);

    // 设置轴线颜色
    QPen axisPen(QColor(80, 80, 80));
    axisPen.setWidth(2);
    axisX->setLinePen(axisPen);
    axisY->setLinePen(axisPen);

    // 默认范围
    axisX->setRange(0, m_timeWindow);

    // 根据图表类型设置初始Y轴范围
    if (title.contains("EEG")) {
        axisY->setRange(m_eegYRange.first, m_eegYRange.second);
    } else if (title.contains("ECG")) {
        axisY->setRange(m_ecgYRange.first, m_ecgYRange.second);
    } else if (title.contains("GSR")) {
        axisY->setRange(m_gsrYRange.first, m_gsrYRange.second);
    }

    // 将轴添加到图表
    chart->addAxis(axisX, Qt::AlignBottom);
    chart->addAxis(axisY, Qt::AlignLeft);

    // 创建各通道的曲线
    QVector<QLineSeries*> seriesList;

    // 修改：为不同类型的图表设置特定颜色
    QColor lineColor;
    if (title.contains("EEG")) {
        // EEG使用蓝色
        lineColor = QColor(0, 0, 255);     // 蓝色
    } else if (title.contains("ECG")) {
        // ECG使用红色
        lineColor = QColor(255, 0, 0);     // 红色
    } else if (title.contains("GSR")) {
        // GSR使用绿色
        lineColor = QColor(0, 128, 0);     // 绿色
    }

    // 只创建一个通道的曲线，而不是多个
    QLineSeries* series = new QLineSeries();

    // 设置显示名称为实际采集的通道
    if (title.contains("EEG")) {
        series->setName("FP1");  // EEG只显示FP1通道
    } else if (title.contains("ECG")) {
        series->setName("ECG5"); // ECG只显示通道5
    } else if (title.contains("GSR")) {
        series->setName("BioZ I"); // GSR只显示BioZ I通道
    }

    // 设置线条样式
    QPen pen;
    pen.setColor(lineColor);
    pen.setWidth(2);
    pen.setStyle(Qt::SolidLine);
    // 增强抗锯齿效果
    pen.setCapStyle(Qt::RoundCap);
    pen.setJoinStyle(Qt::RoundJoin);
    series->setPen(pen);

    // 优化性能设置
    series->setPointsVisible(false);
    series->setUseOpenGL(true); // 使用OpenGL加速渲染

    chart->addSeries(series);
    series->attachAxis(axisX);
    series->attachAxis(axisY);
    seriesList.append(series);

    // 存储相应的曲线列表
    if (title.contains("EEG")) {
        m_eegSeries = seriesList;
    } else if (title.contains("ECG")) {
        m_ecgSeries = seriesList;
    } else if (title.contains("GSR")) {
        m_gsrSeries = seriesList;
    }

    // 图表外观设置
    chart->legend()->setAlignment(Qt::AlignTop);
    chart->legend()->setFont(QFont("Arial", 9));
    chart->legend()->setMarkerShape(QLegend::MarkerShapeRectangle);

    // 移除默认标题
    chart->setTitle("");
    chart->setAnimationOptions(QChart::NoAnimation);

    // 设置图表主题和背景
    chart->setTheme(QChart::ChartThemeLight);

    // 设置渐变背景
    QLinearGradient backgroundGradient;
    backgroundGradient.setStart(QPointF(0, 0));
    backgroundGradient.setFinalStop(QPointF(0, 1));

    // 根据图表类型设置不同的背景色
    if (title.contains("EEG")) {
        backgroundGradient.setColorAt(0.0, QColor(230, 230, 255, 200));
        backgroundGradient.setColorAt(1.0, QColor(255, 255, 255));
    } else if (title.contains("ECG")) {
        backgroundGradient.setColorAt(0.0, QColor(230, 255, 230, 200));
        backgroundGradient.setColorAt(1.0, QColor(255, 255, 255));
    } else if (title.contains("GSR")) {
        backgroundGradient.setColorAt(0.0, QColor(255, 240, 240, 200));
        backgroundGradient.setColorAt(1.0, QColor(255, 255, 255));
    }

    chart->setBackgroundBrush(backgroundGradient);
    chart->setBackgroundRoundness(8);
    chart->setMargins(QMargins(10, 10, 10, 10));

    // 创建图表视图
    QChartView* chartView = new QChartView(chart);
    chartView->setRenderHint(QPainter::Antialiasing, true);  // 确保抗锯齿开启
    chartView->setViewportUpdateMode(QChartView::SmartViewportUpdate);
    chartView->setRenderHint(QPainter::TextAntialiasing, true);

    // 设置图表视图的边框和样式
    chartView->setFrameShape(QFrame::StyledPanel);
    chartView->setFrameShadow(QFrame::Raised);
    chartView->setStyleSheet(
        "QChartView {"
        "  border: 1px solid #bdc3c7;"
        "  border-radius: 5px;"
        "  background-color: white;"
        "}"
        );

    return chartView;
}

void ChartWidget::updateAllCharts() {
    // 如果更新被禁用，直接返回
    if (!m_updatingEnabled) {
        return;
    }

    // 更新所有图表
    updateChart(m_eegSeries, m_eegBuffer, m_eegAxisX, m_eegAxisY, 3, m_eegYRange);
    updateChart(m_ecgSeries, m_ecgBuffer, m_ecgAxisX, m_ecgAxisY, 8, m_ecgYRange);
    updateChart(m_gsrSeries, m_gsrBuffer, m_gsrAxisX, m_gsrAxisY, 2, m_gsrYRange);
}

void ChartWidget::updateChart(QVector<QLineSeries*>& series,
                              QVector<QPointF> buffer[],
                              QValueAxis* axisX,
                              QValueAxis* axisY,
                              int channelCount,
                              QPair<double, double>& yRange) {
    // 如果更新被禁用，直接返回
    if (!m_updatingEnabled) {
        return;
    }

    // 获取当前时间
    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    double currentT = (currentTime - m_startTime) / 1000.0;

    // 计算5秒前的时间点
    double startT = currentT - m_timeWindow;

    double globalMinY = std::numeric_limits<double>::max();  // 使用C++标准极值
    double globalMaxY = std::numeric_limits<double>::lowest();
    double maxX = 0;
    bool hasData = false;
    bool isGsrChart = (&series == &m_gsrSeries);

    // 确定要显示的通道索引
    int channelToShow = 0; // 默认显示第一个通道

    if (&series == &m_ecgSeries) {
        channelToShow = 4; // ECG显示通道5 (索引4)
    } else if (&series == &m_eegSeries) {
        channelToShow = 0; // EEG显示第一个通道
    } else if (&series == &m_gsrSeries) {
        channelToShow = 0; // GSR显示第一个通道
    }

    // 使用互斥锁保护缓冲区读取
    QVector<QPointF> pointsCopy;
    {
        QMutexLocker locker(&m_bufferMutex);

        // 确保通道索引有效且有数据
        if (channelToShow < channelCount && !buffer[channelToShow].isEmpty()) {
            // 创建缓冲区数据的副本，以便在锁外处理
            pointsCopy = buffer[channelToShow];
        }
    }

    // 确保有数据且系列存在
    if (!pointsCopy.isEmpty() && !series.isEmpty()) {
        hasData = true;

        // 获取第一个（也是唯一一个）系列
        QLineSeries* currentSeries = series[0];

        // 准备新的点集合，只包含最近5秒的数据
        QVector<QPointF> newPoints;
        newPoints.reserve(pointsCopy.size()); // 预分配空间以提高性能

        // 从缓冲区中找出最近5秒的数据点
        for (const QPointF& point : pointsCopy) {
            if (point.x() >= startT) {
                newPoints.append(point);

                // 计算Y轴范围 - 只考虑最近5秒的数据
                globalMinY = qMin(globalMinY, point.y());
                globalMaxY = qMax(globalMaxY, point.y());

                // 更新最大X值
                maxX = qMax(maxX, point.x());
            }
        }

        // 确保点按时间顺序排序
        std::sort(newPoints.begin(), newPoints.end(),
                  [](const QPointF& a, const QPointF& b) { return a.x() < b.x(); });

        // 限制显示点数量，避免过多点导致卡顿
        if (newPoints.size() > MAX_DISPLAY_POINTS) {
            // 如果点太多，进行降采样
            QVector<QPointF> sampledPoints;
            sampledPoints.reserve(MAX_DISPLAY_POINTS + 1); // +1 确保有足够空间

            double step = static_cast<double>(newPoints.size()) / MAX_DISPLAY_POINTS;

            // 实现平滑降采样，保留重要特征点
            int lastIndex = -1;
            double maxDelta = 0;
            double lastY = 0;

            // 首先添加第一个点
            if (!newPoints.isEmpty()) {
                sampledPoints.append(newPoints.first());
                lastY = newPoints.first().y();
            }

            // 对于ECG数据，使用更智能的降采样以保留QRS波峰
            if (&series == &m_ecgSeries) {
                for (int i = 1; i < newPoints.size() - 1; i++) {
                    // 计算当前点与前后点的差值，检测波峰和波谷
                    double prevDiff = qAbs(newPoints[i].y() - newPoints[i-1].y());
                    double nextDiff = qAbs(newPoints[i].y() - newPoints[i+1].y());

                    // 如果是显著变化点，保留它
                    if (prevDiff > 10 || nextDiff > 10 || (i % int(step) == 0)) {
                        sampledPoints.append(newPoints[i]);
                        lastY = newPoints[i].y();
                    }
                }
            } else {
                // 对于其他数据类型，使用常规降采样
                for (double j = 1; j < newPoints.size() - 1; j += step) {
                    int index = static_cast<int>(j);
                    if (index < newPoints.size()) {
                        sampledPoints.append(newPoints[index]);
                    }
                }
            }

            // 确保包含最后一个点
            if (!newPoints.isEmpty() && !sampledPoints.isEmpty() &&
                sampledPoints.last().x() != newPoints.last().x()) {
                sampledPoints.append(newPoints.last());
            }

            // 替换所有点
            currentSeries->replace(sampledPoints);
        } else {
            // 点数量适中，直接替换
            currentSeries->replace(newPoints);
        }
    }

    // 如果有数据，更新X轴和Y轴范围
    if (hasData) {
        // 更新X轴范围，保持滑动窗口效果，始终显示最近5秒
        axisX->setRange(currentT - m_timeWindow, currentT);

        // 确保所有图表的Y轴范围相对一致
        if (globalMinY != std::numeric_limits<double>::max() &&
            globalMaxY != std::numeric_limits<double>::lowest() &&
            globalMinY < globalMaxY) {

            // 计算数据范围
            double range = globalMaxY - globalMinY;

            // 防止范围过小导致图表波动过大
            if (range < 1.0) {
                range = 1.0;
            }

            // 计算填充，使数据占据90%的位置
            double padding = range * Y_AXIS_PADDING_PERCENT;

            // 设置新范围
            double newMin = globalMinY - padding;
            double newMax = globalMaxY + padding;

            // 强制更新Y轴范围
            axisY->setRange(newMin, newMax);
            yRange.first = newMin;
            yRange.second = newMax;
        }
    }
}


void ChartWidget::appendEegData(double fp1, double fpz, double fp2, qint64 timestamp) {
    // 如果更新被禁用，则不添加数据
    if (!m_updatingEnabled) {
        return;
    }

    // 将绝对时间戳转换为相对秒
    double t = (timestamp - m_startTime) / 1000.0;

    // 将数据点添加到缓冲区 - 仍然存储所有通道的数据
    m_eegBuffer[0].append(QPointF(t, fp1));
    m_eegBuffer[1].append(QPointF(t, fpz));
    m_eegBuffer[2].append(QPointF(t, fp2));
}


void ChartWidget::appendGsrData(double bioZI, double bioZQ, qint64 timestamp) {
    if (!m_updatingEnabled) {
        return;
    }

    double t = (timestamp - m_startTime) / 1000.0;

    // 修改：使用更细粒度的锁，减少与ECG数据添加的竞争
    {
        QMutexLocker locker(&m_gsrBufferMutex); // 使用GSR专用的互斥锁

        m_gsrBuffer[0].append(QPointF(t, bioZI));
        m_gsrBuffer[1].append(QPointF(t, bioZQ));

        // 限制缓冲区大小
        for (int i = 0; i < 2; i++) {
            while (m_gsrBuffer[i].size() > MAX_POINTS_PER_BUFFER) {
                m_gsrBuffer[i].removeFirst();
            }
        }
    } // 锁的作用域结束，立即释放
}

void ChartWidget::appendEcgData(const QVector<double> &values, qint64 timestamp)
{
    // 如果更新被禁用，则不添加数据
    if (!m_updatingEnabled) {
        return;
    }

    // 将绝对时间戳转换为相对秒
    double t = (timestamp - m_startTime) / 1000.0;

    // 确保数据点数量正确
    int count = qMin(values.size(), 8);

    // 使用互斥锁保护缓冲区操作
    QMutexLocker locker(&m_bufferMutex);

    // 批量添加所有通道数据到缓冲区 - 仍然存储所有通道的数据
    for (int i = 0; i < count; i++) {
        // 添加数据点到缓冲区
        m_ecgBuffer[i].append(QPointF(t, values[i]));

        // 限制缓冲区大小，只保留最近的MAX_BUFFER_SIZE个点
        while (m_ecgBuffer[i].size() > MAX_BUFFER_SIZE) {
            m_ecgBuffer[i].removeFirst();
        }
    }

    // 增加批处理计数
    m_ecgDataBatchCounter++;

    // 修改：增加批处理阈值，减少更新频率
    if (m_ecgDataBatchCounter >= 100) {  // 从50增加到100
        m_ecgDataBatchCounter = 0;

        // 解锁后更新图表，避免长时间持有锁
        locker.unlock();

        // 如果定时器不活跃，手动触发更新
        if (!m_updateTimer->isActive()) {
            updateAllCharts();
        }
    }
}
// 统一的图表视觉增强方法
void ChartWidget::enhanceVisualization() {
    // 修改：不再添加垂直偏移，因为现在只显示一个通道
    // 设置EEG图表（蓝色）
    if (!m_eegSeries.isEmpty()) {
        QPen pen = m_eegSeries[0]->pen();
        pen.setColor(QColor(0, 0, 255)); // 蓝色
        pen.setWidth(2);
        pen.setCapStyle(Qt::RoundCap);  // 添加圆形线帽
        pen.setJoinStyle(Qt::RoundJoin); // 添加圆形连接点
        m_eegSeries[0]->setPen(pen);
    }

    // 设置ECG图表（红色）
    if (!m_ecgSeries.isEmpty()) {
        QPen pen = m_ecgSeries[0]->pen();
        pen.setColor(QColor(255, 0, 0)); // 红色
        pen.setWidth(2);
        pen.setCapStyle(Qt::RoundCap);  // 添加圆形线帽
        pen.setJoinStyle(Qt::RoundJoin); // 添加圆形连接点
        m_ecgSeries[0]->setPen(pen);
    }

    // 设置GSR图表（绿色）
    if (!m_gsrSeries.isEmpty()) {
        QPen pen = m_gsrSeries[0]->pen();
        pen.setColor(QColor(0, 128, 0)); // 绿色
        pen.setWidth(2);
        pen.setCapStyle(Qt::RoundCap);  // 添加圆形线帽
        pen.setJoinStyle(Qt::RoundJoin); // 添加圆形连接点
        m_gsrSeries[0]->setPen(pen);
    }

    // 设置图表标题和样式
    setupChartStyle(m_eegChartView, m_eegAxisX, m_eegAxisY, "EEG 脑电实时监测");
    setupChartStyle(m_ecgChartView, m_ecgAxisX, m_ecgAxisY, "ECG 心电实时监测");
    setupChartStyle(m_gsrChartView, m_gsrAxisX, m_gsrAxisY, "GSR 皮电实时监测");
}


void ChartWidget::setupChartStyle(QChartView* chartView,
                                  QValueAxis* axisX,
                                  QValueAxis* axisY,
                                  const QString& title) {
    if (!chartView) return;

    QChart* chart = chartView->chart();

    // 设置标题样式
    QFont titleFont = chart->titleFont();
    titleFont.setBold(true);
    titleFont.setPointSize(12);
    chart->setTitleFont(titleFont);
    chart->setTitle(title);

    // 设置网格线样式
    QPen gridPen(QColor(200, 200, 220, 150));
    gridPen.setWidth(1);
    axisX->setGridLinePen(gridPen);
    axisY->setGridLinePen(gridPen);

    // 增加网格线密度
    axisX->setTickCount(10);
    axisY->setTickCount(8);

    // 确保所有图表Y轴范围相似
    // 这里可以设置一个统一的Y轴范围，但我们保留动态调整以适应数据

    // 启用图例
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignRight);

    // 应用更新
    chartView->update();
}
// 统一的图表视觉增强辅助方法
void ChartWidget::enhanceChartVisualization(QVector<QLineSeries*>& series,
                                            QChartView* chartView,
                                            QValueAxis* axisX,
                                            QValueAxis* axisY,
                                            const QString& title,
                                            double offsetStep) {
    // 增加通道之间的垂直偏移，使波形更清晰
    for (int i = 0; i < series.size(); i++) {
        QLineSeries* currentSeries = series[i];

        // 获取当前所有点
        QVector<QPointF> points = currentSeries->points();

        // 为每个通道添加垂直偏移
        double offset = offsetStep * i;

        // 应用偏移
        for (int j = 0; j < points.size(); j++) {
            points[j].setY(points[j].y() + offset);
        }

        // 替换所有点
        currentSeries->replace(points);

        // 确保线宽统一
        QPen pen = currentSeries->pen();
        pen.setWidth(2);
        currentSeries->setPen(pen);

        // 更新通道名称，显示偏移信息
        QString baseName = currentSeries->name();
        if (baseName.contains("+")) {
            baseName = baseName.split("+").first().trimmed();
        }
        currentSeries->setName(QString("%1 (+%2)").arg(baseName).arg(offset));
    }

    // 设置图表主题
    QChart* chart = chartView->chart();

    // 设置标题样式
    QFont titleFont = chart->titleFont();
    titleFont.setBold(true);
    titleFont.setPointSize(12);
    chart->setTitleFont(titleFont);
    chart->setTitle(title);

    // 设置网格线样式
    QPen gridPen(QColor(200, 200, 220, 150));
    gridPen.setWidth(1);
    axisX->setGridLinePen(gridPen);
    axisY->setGridLinePen(gridPen);

    // 增加网格线密度
    axisX->setTickCount(10);
    axisY->setTickCount(8);

    // 启用图例
    chart->legend()->setVisible(true);
    chart->legend()->setAlignment(Qt::AlignRight);

    // 应用更新
    chartView->update();
}

void ChartWidget::setTimeWindow(double seconds) {
    if (seconds > 0) {
        m_timeWindow = seconds;

        // 更新所有图表的X轴范围
        updateTimeWindow(m_eegSeries, m_eegAxisX);
        updateTimeWindow(m_ecgSeries, m_ecgAxisX);
        updateTimeWindow(m_gsrSeries, m_gsrAxisX);
    }
}

// 辅助方法：更新时间窗口
void ChartWidget::updateTimeWindow(QVector<QLineSeries*>& series, QValueAxis* axisX) {
    if (!series.isEmpty() && !series[0]->points().isEmpty()) {
        double lastX = series[0]->points().last().x();

        if (lastX < m_timeWindow) {
            // 图表还未画满，X轴范围固定从0开始
            axisX->setRange(0, m_timeWindow);
        } else {
            // 图表已经画满，X轴开始滑动
            axisX->setRange(lastX - m_timeWindow, lastX);
        }
    } else {
        // 没有数据点时，设置默认范围
        axisX->setRange(0, m_timeWindow);
    }
}

void ChartWidget::clearAllData() {
    // 停止更新
    stopUpdating();

    // 清除所有系列的数据点
    for (auto series : m_eegSeries) {
        series->clear();
    }

    for (auto series : m_ecgSeries) {
        series->clear();
    }

    for (auto series : m_gsrSeries) {
        series->clear();
    }

    // 清除所有缓冲区
    for (int i = 0; i < 3; i++) {
        m_eegBuffer[i].clear();
    }

    for (int i = 0; i < 8; i++) {
        m_ecgBuffer[i].clear();
    }

    for (int i = 0; i < 2; i++) {
        m_gsrBuffer[i].clear();
    }

    // 重置开始时间
    m_startTime = QDateTime::currentMSecsSinceEpoch();

    // 重置计数器
    m_ecgDataBatchCounter = 0;

    // 重置Y轴范围
    m_eegYRange = QPair<double, double>(-150, 150);
    m_ecgYRange = QPair<double, double>(-100, 300);
    m_gsrYRange = QPair<double, double>(-1000, 1000);

    // 更新坐标轴
    m_eegAxisX->setRange(0, m_timeWindow);
    m_eegAxisY->setRange(m_eegYRange.first, m_eegYRange.second);

    m_ecgAxisX->setRange(0, m_timeWindow);
    m_ecgAxisY->setRange(m_ecgYRange.first, m_ecgYRange.second);

    m_gsrAxisX->setRange(0, m_timeWindow);
    m_gsrAxisY->setRange(m_gsrYRange.first, m_gsrYRange.second);
}

void ChartWidget::setDelayedDisplayMode(bool enabled)
{
    m_delayedDisplayMode = enabled;

    if (enabled) {
        // 停止实时更新
        stopUpdating();

        // 清空当前图表
        clearAllData();

        // 设置状态提示
        QLabel* statusLabel = new QLabel("延迟显示模式已启用，从数据库加载数据...", this);
        statusLabel->setStyleSheet("background-color: rgba(255, 255, 200, 200); padding: 5px; border-radius: 3px;");
        statusLabel->setAlignment(Qt::AlignCenter);
        m_mainLayout->insertWidget(0, statusLabel);

        // 2秒后自动隐藏提示
        QTimer::singleShot(2000, [statusLabel]() {
            statusLabel->deleteLater();
        });

        // 启动批处理定时器，每200ms处理一批数据
        if (!m_batchProcessTimer) {
            m_batchProcessTimer = new QTimer(this);
            connect(m_batchProcessTimer, &QTimer::timeout, this, &ChartWidget::processBatchData);
        }
        m_batchProcessTimer->start(200);
    } else {
        // 恢复实时更新
        if (m_batchProcessTimer) {
            m_batchProcessTimer->stop();
        }

        // 清空当前图表
        clearAllData();

        // 重置开始时间
        m_startTime = QDateTime::currentMSecsSinceEpoch();

        // 恢复实时更新
        startUpdating();

        // 设置状态提示
        QLabel* statusLabel = new QLabel("已恢复实时显示模式", this);
        statusLabel->setStyleSheet("background-color: rgba(200, 255, 200, 200); padding: 5px; border-radius: 3px;");
        statusLabel->setAlignment(Qt::AlignCenter);
        m_mainLayout->insertWidget(0, statusLabel);

        // 2秒后自动隐藏提示
        QTimer::singleShot(2000, [statusLabel]() {
            statusLabel->deleteLater();
        });
    }
}

void ChartWidget::loadHistoricalData(DatabaseManager* db, qint64 startTime, qint64 endTime)
{
    if (!m_delayedDisplayMode || !db) {
        return;
    }

    // 清空现有数据
    clearAllData();

    // 设置新的开始时间
    m_startTime = startTime;

    // 从数据库查询心电数据
    QSqlQuery ecgQuery;
    ecgQuery.prepare("SELECT timestamp, ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8 FROM ecg_data "
                     "WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp ASC");
    ecgQuery.addBindValue(startTime);
    ecgQuery.addBindValue(endTime);

    if (!ecgQuery.exec()) {
        qWarning() << "查询ECG历史数据失败:" << ecgQuery.lastError().text();
    } else {
        // 准备心电批处理缓冲区
        m_ecgBatchBuffer.clear();

        // 读取心电数据并添加到批处理缓冲区
        while (ecgQuery.next()) {
            qint64 timestamp = ecgQuery.value(0).toLongLong();
            QVector<QPointF> dataPoints;

            // 计算相对时间（秒）
            double t = (timestamp - m_startTime) / 1000.0;

            // 读取8个通道的数据
            for (int i = 0; i < 8; i++) {
                double value = ecgQuery.value(i + 1).toDouble();
                dataPoints.append(QPointF(t, value));
            }

            // 添加到批处理缓冲区
            m_ecgBatchBuffer.append(dataPoints);
        }
    }

    // 从数据库查询脑电数据
    QSqlQuery eegQuery;
    eegQuery.prepare("SELECT timestamp, fp1, fpz, fp2 FROM eeg_data "
                     "WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp ASC");
    eegQuery.addBindValue(startTime);
    eegQuery.addBindValue(endTime);

    if (!eegQuery.exec()) {
        qWarning() << "查询EEG历史数据失败:" << eegQuery.lastError().text();
    } else {
        // 准备脑电批处理缓冲区
        m_eegBatchBuffer.clear();

        // 读取脑电数据并添加到批处理缓冲区
        while (eegQuery.next()) {
            qint64 timestamp = eegQuery.value(0).toLongLong();
            QVector<QPointF> dataPoints;

            // 计算相对时间（秒）
            double t = (timestamp - m_startTime) / 1000.0;

            // 读取3个通道的数据
            for (int i = 0; i < 3; i++) {
                double value = eegQuery.value(i + 1).toDouble();
                dataPoints.append(QPointF(t, value));
            }

            // 添加到批处理缓冲区
            m_eegBatchBuffer.append(dataPoints);
        }
    }

    // 如果有数据，开始处理
    if (!m_ecgBatchBuffer.isEmpty() || !m_eegBatchBuffer.isEmpty()) {
        // 启动批处理定时器
        if (!m_batchProcessTimer->isActive()) {
            m_batchProcessTimer->start(200);
        }
    }
}

void ChartWidget::processBatchData()
{
    bool hasMoreData = false;

    // 处理心电数据
    if (!m_ecgBatchBuffer.isEmpty()) {
        hasMoreData = true;

        // 每次处理一批数据（最多100个样本）
        int batchSize = qMin(100, m_ecgBatchBuffer.size());

        // 处理每个样本
        for (int i = 0; i < batchSize; i++) {
            if (m_ecgBatchBuffer.isEmpty()) break;

            // 获取一个样本（包含所有通道的数据点）
            QVector<QPointF> sample = m_ecgBatchBuffer.takeFirst();

            // 将数据点添加到各通道的缓冲区
            for (int ch = 0; ch < qMin(sample.size(), 8); ch++) {
                m_ecgBuffer[ch].append(sample[ch]);
            }
        }
    }

    // 处理脑电数据
    if (!m_eegBatchBuffer.isEmpty()) {
        hasMoreData = true;

        // 每次处理一批数据（最多100个样本）
        int batchSize = qMin(100, m_eegBatchBuffer.size());

        // 处理每个样本
        for (int i = 0; i < batchSize; i++) {
            if (m_eegBatchBuffer.isEmpty()) break;

            // 获取一个样本（包含所有通道的数据点）
            QVector<QPointF> sample = m_eegBatchBuffer.takeFirst();

            // 将数据点添加到各通道的缓冲区
            for (int ch = 0; ch < qMin(sample.size(), 3); ch++) {
                m_eegBuffer[ch].append(sample[ch]);
            }
        }
    }

    // 如果没有更多数据，停止定时器
    if (!hasMoreData) {
        m_batchProcessTimer->stop();
    }

    // 更新图表
    updateAllCharts();
}
